package com.bytenebula.asteroid;

import com.bytenebula.ResultCodes;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;

import java.io.Serializable;
import java.time.LocalDateTime;

@Data
@NoArgsConstructor
public class ServiceResult implements Serializable {

    public ServiceResult(ResultCodes code) {
        this.code = code.getCode();
        this.success = code == ResultCodes.SUCCESS;
        this.message = code.getMessage();
    }

    public ServiceResult(@NonNull String code, String message) {
        this.code = code;
        this.success = code.equals(ResultCodes.SUCCESS.getCode());
        this.message = message;
    }

    @NonNull
    private String code;
    private Boolean success;
    private String message;
    private Object data;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @JsonSerialize(using = LocalDateTimeSerializer.class)
    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    private LocalDateTime timestamp = LocalDateTime.now();

    public static ServiceResult success() {
        return new ServiceResult(ResultCodes.SUCCESS);
    }

    public static ServiceResult success(Object data) {
        ServiceResult result = ServiceResult.success();
        if (data != null) result.setData(data);
        return result;
    }

    public static ServiceResult fail() {
        return new ServiceResult(ResultCodes.FAILURE);
    }

    public static ServiceResult fail(String code, String message, Exception ex) {
        ServiceResult result = new ServiceResult(code, message);
        result.setData(ex);
        return result;
    }

    public static ServiceResult fail(Object data) {
        ServiceResult result = ServiceResult.fail();
        if (data != null) result.setData(data);
        return result;
    }

    public static ServiceResult exception(Exception ex) {
        ServiceResult result = new ServiceResult(ResultCodes.EXCEPTION.getCode(),
                ResultCodes.EXCEPTION.getMessage());
        result.setData(ex.getMessage());
        return result;
    }
}
